﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace G.APITest.Data
{

    public enum ClassType
    {
        CSharp,
        Andriod,
        Object_C,
        Object_C_noARC
    }


    public class CreateClassTreeNode
    {
        public static ClassType ClassType = Data.ClassType.Andriod;

        public CreateClassTreeNode()
        {
            Nodes = new ObservableCollection<CreateClassTreeNode>();
        }
        public string Key { get; set; }

        public System.Json.JsonValue Value { get; set; }

        public System.Json.JsonType JsonType { get; set; }

        public ObservableCollection<CreateClassTreeNode> Nodes { get; private set; }

        //private string code = string.Empty;
        //public string Code
        //{
        //    get
        //    {
        //        if (code == string.Empty)
        //        {
        //            code = this.ToString();
        //        }
        //        return code;
        //    }
        //    set
        //    {
        //        code = value;
        //    }
        //}
        public override string ToString()
        {
            System.Text.StringBuilder[] sb;
            if (ClassType == Data.ClassType.Object_C || ClassType == Data.ClassType.Object_C_noARC)
            {
                sb = new System.Text.StringBuilder[2] { new System.Text.StringBuilder(), new System.Text.StringBuilder() };
            }
            else
                sb = new System.Text.StringBuilder[1] { new System.Text.StringBuilder() };
            switch (JsonType)
            {
                case System.Json.JsonType.Object:
                    GetClassString(sb, this);
                    break;
                case System.Json.JsonType.Array:
                    var array = Value as System.Json.JsonArray;
                    if (array.Count == 0)
                        GetPropertyString(sb, this);
                    else
                    {
                        var v = array[0];
                        if (v.JsonType == System.Json.JsonType.Object)
                        {
                            GetClassString(sb, this);
                        }
                    }
                    break;
                default:
                    GetPropertyString(sb, this);
                    break;
            }
            if (ClassType == Data.ClassType.Object_C || ClassType == Data.ClassType.Object_C_noARC)
            {
                return sb[0].ToString() + "\r\n----------------------我是分割线-----------------\r\n" + sb[1].ToString();
            }
            else
            {
                return sb[0].ToString();
            }
        }

        private static void GetClassString(System.Text.StringBuilder[] sb, CreateClassTreeNode node)
        {
            //b.Append("using System;\r\n");
            //b.Append("using System.Runtime.Serialization;\r\n");
            switch (ClassType)
            {
                case Data.ClassType.CSharp:
                    sb[0].Append("\t[DataContract]\r\n");
                    sb[0].Append("\tpublic class " + UpFirstChar(WorldTransform(node.Key)[0]) + "\r\n");
                    sb[0].Append("\t{\r\n");
                    foreach (var n in node.Nodes)
                    {
                        GetPropertyString(sb, n);
                    }
                    sb[0].Append("\t}");
                    break;
                case Data.ClassType.Andriod:
                    sb[0].Append("public class " + UpFirstChar(WorldTransform(node.Key)[0]) + "{\r\n\r\n");
                    foreach (var n in node.Nodes)
                    {
                        GetPropertyString(sb, n);
                    }
                    sb[0].Append("}");
                    break;
                case Data.ClassType.Object_C_noARC:
                case Data.ClassType.Object_C:
                    sb[0].Append("#import \"YekBaseData.h\"\r\n");
                    sb[0].Append(string.Format("@interface {0} : YekBaseData", UpFirstChar(WorldTransform(node.Key)[0]) + "Data"));
                    sb[0].Append("{\r\n");
                    foreach (var n in node.Nodes)
                    {
                        GetGetPropertyString_objc(sb[0], n);
                    }
                    sb[0].Append("}\r\n");

                    sb[1].Append(string.Format("#import \"{0}.h\"\r\n\r\n", UpFirstChar(WorldTransform(node.Key)[0]) + "Data"));
                    sb[1].Append(string.Format("@implementation {0}\r\n", UpFirstChar(WorldTransform(node.Key)[0]) + "Data"));
                    foreach (var n in node.Nodes)
                    {
                        GetPropertyString(sb, n);
                    }
                    sb[0].Append("@end\r\n");
                    sb[1].Append("@end\r\n");
                    break;
            }

        }
        private static void GetGetPropertyString_objc(System.Text.StringBuilder sb, CreateClassTreeNode node)
        {
            string typeName = GetTypeString(node);
            sb.Append(string.Format("\t{0} *_{1};\r\n", typeName, node.Key));
        }
        /// <summary>
        /// 获取属性表达式字符串
        /// </summary>
        /// <param name="sb"></param>
        private static void GetPropertyString(System.Text.StringBuilder[] sb, CreateClassTreeNode node)
        {
            string name = node.Key;
            switch (ClassType)
            {
                case Data.ClassType.CSharp:
                    sb[0].Append(string.Format("\t\t[DataMember(Name = \"{0}\")]\r\n\t\tpublic {1} {2} ", name, GetTypeString(node), UpFirstChar(name)));
                    sb[0].Append("{ get; set; }\r\n\r\n");
                    break;
                case Data.ClassType.Andriod:
                    sb[0].Append(string.Format("\tprivate {0} {1};\r\n\r\n", GetTypeString(node), name));
                    sb[0].Append(string.Format("\tpublic {0} get{1}()", GetTypeString(node), UpFirstChar(name)));
                    sb[0].Append("{\r\n");
                    sb[0].Append(string.Format("\t\treturn {0};\r\n", name));
                    sb[0].Append("\t}\r\n\r\n");
                    sb[0].Append(string.Format("\tpublic void set{0}({1} {2})", UpFirstChar(name), GetTypeString(node), name));
                    sb[0].Append("{\r\n");
                    sb[0].Append(string.Format("\t\tthis.{0}={0};\r\n", name));
                    sb[0].Append("\t}\r\n\r\n");
                    break;
                case Data.ClassType.Object_C:
                    string typeName = GetTypeString(node);
                    sb[0].Append(string.Format("@property (nonatomic, readonly) {0} *{1};\r\n", typeName, name));
                    sb[1].Append(string.Format("- ({0} *)", typeName) + name + " {\r\n");
                    if (typeName == "NSString")
                    {
                        sb[1].Append(string.Format("\tif(_{0}==nil)\r\n", name));
                        sb[1].Append(string.Format("\t\t _{0}=[[kGlobalValue m_IStringHelper] strOrEmpty:[mDictionary objectForKey:@\"{0}\"]];\r\n", name));
                        sb[1].Append(string.Format("\treturn _{0};\r\n", name));
                    }
                    else if (typeName == "NSArray")
                    {
                        var array = node.Value as System.Json.JsonArray;
                        if (array.Count != 0 && (array[0].JsonType == System.Json.JsonType.Object || array[0].JsonType == System.Json.JsonType.Array))
                        {
                            string arrayTypeName = UpFirstChar(WorldTransform(node.Key)[0]);
                            if (array[0].JsonType == System.Json.JsonType.Object)
                                arrayTypeName += "Data";
                            sb[1].Append(string.Format("\tif(_{0}==nil)", name));
                            sb[1].Append("{\r\n");
                            sb[1].Append("\t\tNSMutableArray *retArray = nil;\r\n");
                            sb[1].Append(string.Format("\t\tNSArray *listValue = [mDictionary objectForKey:@\"{0}\"];\r\n", name));
                            sb[1].Append("\t\tif ( listValue && [listValue isKindOfClass:[NSArray class]] ) {\r\n");
                            sb[1].Append("\t\t\tfor (NSDictionary *dict in listValue) {\r\n");
                            sb[1].Append(string.Format("\t\t\t\t{0} *data = [[{0} alloc] initWithJsonObject:dict];\r\n", arrayTypeName));
                            sb[1].Append("\t\t\t\tif ( data ) {\r\n");
                            sb[1].Append("\t\t\t\t\tif ( retArray == nil ) {\r\n");
                            sb[1].Append("\t\t\t\t\t\tretArray = [[NSMutableArray alloc] initWithCapacity:5];\r\n");
                            sb[1].Append("\t\t\t\t\t}\r\n");
                            sb[1].Append("\t\t\t\t\t[retArray addObject:data];\r\n");
                            sb[1].Append("\t\t\t\t}\r\n");
                            sb[1].Append("\t\t\t}\r\n");
                            sb[1].Append("\t\t}\r\n");
                            sb[1].Append(string.Format("\t\t_{0}=retArray;\r\n", name));
                            //sb[1].Append("\t\treturn retArray;\r\n");
                            sb[1].Append("\t}\r\n");
                            sb[1].Append(string.Format("\treturn  _{0};\r\n", name));
                        }
                        else
                        {
                            sb[1].Append(string.Format("\treturn [mDictionary objectForKey:@\"{0}\"];\r\n", name));
                        }
                    }
                    else
                    {
                        sb[1].Append(string.Format("\tif(_{0}==nil)\r\n", name));
                        sb[1].Append(string.Format("\t\t_{1} = [[{0} alloc] initWithJsonObject:[mDictionary getDictionary:@\"{1}\"]];\r\n", typeName, name));
                        sb[1].Append(string.Format("\treturn  _{0};\r\n", name));
                    }
                    sb[1].Append("}\r\n\r\n");
                    break;

                case Data.ClassType.Object_C_noARC:
                    {
                        string _typeName = GetTypeString(node);
                        sb[0].Append(string.Format("@property (nonatomic, readonly) {0} *{1};\r\n", _typeName, name));
                        sb[1].Append(string.Format("- ({0} *)", _typeName) + name + " {\r\n");
                        if (_typeName == "NSString")
                        {
                            sb[1].Append(string.Format("\tif(_{0}==nil)\r\n", name));
                            sb[1].Append(string.Format("\t\t _{0}=[[kGlobalValue m_IStringHelper] strOrEmpty:[mDictionary objectForKey:@\"{0}\"]];\r\n", name));
                            sb[1].Append(string.Format("\treturn _{0};\r\n", name));
                        }
                        else if (_typeName == "NSArray")
                        {
                            var array = node.Value as System.Json.JsonArray;
                            if (array.Count != 0 && (array[0].JsonType == System.Json.JsonType.Object || array[0].JsonType == System.Json.JsonType.Array))
                            {
                                string arrayTypeName = UpFirstChar(WorldTransform(node.Key)[0]);
                                if (array[0].JsonType == System.Json.JsonType.Object)
                                    arrayTypeName += "Data";
                                sb[1].Append(string.Format("\tif(_{0}==nil)", name));
                                sb[1].Append("{\r\n");
                                sb[1].Append("\t\tNSMutableArray *retArray = nil;\r\n");
                                sb[1].Append(string.Format("\t\tNSArray *listValue = [mDictionary objectForKey:@\"{0}\"];\r\n", name));
                                sb[1].Append("\t\tif ( listValue && [listValue isKindOfClass:[NSArray class]] ) {\r\n");
                                sb[1].Append("\t\t\tfor (NSDictionary *dict in listValue) {\r\n");
                                sb[1].Append(string.Format("\t\t\t\t{0} *data = [[[{0} alloc] initWithJsonObject:dict] autorelease];\r\n", arrayTypeName));
                                sb[1].Append("\t\t\t\tif ( data ) {\r\n");
                                sb[1].Append("\t\t\t\t\tif ( retArray == nil ) {\r\n");
                                sb[1].Append("\t\t\t\t\t\tretArray = [[NSMutableArray alloc] initWithCapacity:5];\r\n");
                                sb[1].Append("\t\t\t\t\t}\r\n");
                                sb[1].Append("\t\t\t\t\t[retArray addObject:data];\r\n");
                                sb[1].Append("\t\t\t\t}\r\n");
                                sb[1].Append("\t\t\t}\r\n");
                                sb[1].Append("\t\t}\r\n");
                                sb[1].Append(string.Format("\t\t_{0}=retArray;\r\n", name));
                                //sb[1].Append("\t\treturn retArray;\r\n");
                                sb[1].Append("\t}\r\n");
                                sb[1].Append(string.Format("\treturn  [_{0} autorelease];\r\n", name));
                            }
                            else
                            {
                                sb[1].Append(string.Format("\treturn [mDictionary objectForKey:@\"{0}\"];\r\n", name));
                            }
                        }
                        else
                        {
                            sb[1].Append(string.Format("\tif(_{0}==nil)\r\n", name));
                            sb[1].Append(string.Format("\t\t_{1} = [[[{0} alloc] initWithJsonObject:[mDictionary getDictionary:@\"{1}\"]] autorelease];\r\n", _typeName, name));
                            sb[1].Append(string.Format("\treturn  _{0};\r\n", name));
                        }
                        sb[1].Append("}\r\n\r\n");
                    }
                    break;
            }
        }

        private static string UpFirstChar(string str)
        {
            if (str.Length == 0)
                return str;
            char f = str[0];
            char temp = f;
            if (f >= 97 && f <= 122)
                temp = (char)(f - 32);
            if (str.Length == 1)
                return temp.ToString();
            return temp + str.Substring(1);
        }

        private static string GetTypeString(CreateClassTreeNode node)
        {
            if (ClassType == Data.ClassType.Object_C || ClassType== Data.ClassType.Object_C_noARC)
            {
                switch (node.JsonType)
                {
                    case System.Json.JsonType.Boolean:
                    case System.Json.JsonType.Number:
                    case System.Json.JsonType.String:
                        return "NSString";
                    case System.Json.JsonType.Array:
                        return "NSArray";
                    case System.Json.JsonType.Object:
                        return UpFirstChar(node.Key) + "Data";
                    default:
                        return UpFirstChar(node.Key);
                }
            }
            else
            {
                switch (node.JsonType)
                {
                    case System.Json.JsonType.Boolean:
                        return "bool";
                    case System.Json.JsonType.Number:
                        return "double";
                    case System.Json.JsonType.String:
                        return "String";
                    case System.Json.JsonType.Array:
                        var array = node.Value as System.Json.JsonArray;
                        if (array.Count == 0)
                        {
                            return "String[]";
                        }
                        else if (array[0].JsonType == System.Json.JsonType.Object || array[0].JsonType == System.Json.JsonType.Array)
                        {
                            return UpFirstChar(WorldTransform(node.Key)[0]) + "[]";
                        }
                        else
                            return "String[]";
                    case System.Json.JsonType.Object:
                        return UpFirstChar(node.Key);
                    default:
                        return UpFirstChar(node.Key);
                }
            }
        }


        /// <summary>
        /// 单词单复数转换函数,本函数对2个或2个字母以上单词有效
        /// </summary>
        /// <param name="world">待转换的单词</param>
        /// <returns>返回一个长度为2的字符串数组,第一个值为单数单词,第二个为复数单词</returns>
        private static string[] WorldTransform(string world)
        {
            world = world.ToLower();//将单词转成小写形式
            string vowel = "aoeiu";//声明元音字符串
            int length = world.Length;//获取单词字符长度待用
            string[] worlds = new string[2];//声明一个二维字符串数组
            if (length == 1)
            {
                worlds[0] = world;//存储单词单数形式
                worlds[1] = world;//存储单词复数形式
                return worlds;
            }
            else
            {
                char last = world[length - 1];//取出单词最后一个字符待用
                char last2 = world[length - 2];//取出单词倒数第二个字符待用
                char last3 = ' ';
                if (length >= 3)
                    last3 = world[length - 3];//取出单词倒数第三个字符待用
                char last4 = ' ';
                if (length >= 4)
                    last4 = world[length - 4];//取出单词倒数第四个字符待用
                worlds[0] = world;//存储单词单数形式
                worlds[1] = world;//存储单词复数形式


                if (length == 1)
                {
                    return worlds;
                }
                if (last != 's' || length <= 2)
                {
                    //单词最后一个字母不为"s"，则可判断为单数形式
                    switch (last)
                    {
                        case 'y':
                            if (vowel.IndexOf(last2) < 0)
                            {
                                worlds[1] = worlds[1].Substring(0, length - 1) + "i";
                                worlds[1] += "es";
                            }
                            else
                                worlds[1] += "s";
                            break;
                        case 'f':
                            worlds[1] = worlds[1].Substring(0, length - 1) + "v";
                            worlds[1] += "es";
                            break;
                        case 'e':
                            if (last2 == 'f')
                            {
                                worlds[1] = worlds[1].Substring(0, length - 2) + "ves";
                            }
                            else
                                worlds[1] += "s";
                            break;
                        case 'o':
                            worlds[1] += "es";
                            break;
                        case 'z':
                            worlds[1] += "es";
                            break;
                        case 's':
                            worlds[1] += "es";
                            break;
                        case 'x':
                            worlds[1] += "es";
                            break;
                        case 'h':
                            if (last2 == 'c' || last2 == 's')
                                worlds[1] += "es";
                            else
                                worlds[1] += "s";
                            break;
                        default:
                            worlds[1] += "s";
                            break;
                    }
                    return worlds;
                }
                else
                {
                    if (last2 == 'e')
                    {
                        //单词最后两个字母为“es”，则可判断其为复数形式
                        if (last3 == 'z' || last3 == 'x' || last3 == 's' || last3 == 'h' || last3 == 'o')
                            worlds[0] = worlds[0].Remove(length - 2);
                        else if (last3 == 'i')
                        {
                            if (length >= 4)
                            {
                                if (vowel.IndexOf(last4) < 0)
                                {
                                    worlds[0] = worlds[0].Remove(length - 2);
                                    worlds[0] = worlds[0].Substring(0, length - 3) + "y";
                                }
                                else
                                    worlds[0] = worlds[0].Remove(length - 2);
                            }
                        }
                        else if (last3 == 'v')
                        {
                            worlds[0] = worlds[0].Remove(length - 3);
                            worlds[0] += "f";//此步骤会产生误差。因为大多数的“f”、“fe”结尾单词中多以“f”结尾(还没有调查过)，顾忽略“fe”。要避免误差只能用词库了。
                        }
                        else
                        {
                            worlds[0] = worlds[0].Remove(length - 1);
                        }
                    }
                    else
                    {
                        worlds[0] = worlds[0].Remove(length - 1);//此步骤误差最大，当单词最后一个字母为s时，很难判断它是复数还是单数，目前还没有找到判断的规律，估计要用到词库此才行。
                    }
                    return worlds;
                }
            }
        }
    }
}
